﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Obra.Common;

namespace Obra.SmugMug.Api
{
    /// <summary>
    /// This class is use to inject custom data into the out going message, and
    /// debugging of communication.
    /// </summary>
    internal sealed class MessageInspector :
        IClientMessageInspector
    {
        #region IClientMessageInspector Members

        /// <summary>
        /// Enables inspection or modification of a message after a reply message
        /// is received but prior to passing it back to the client application.
        /// </summary>
        /// <param name="reply">
        /// The message to be transformed into types and handed back to the 
        /// client application.
        /// </param>
        /// <param name="correlationState">
        /// Correlation state data
        /// </param>
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
            Log.Debug(
                reply.ToString(),
                LogCategory.REST,
                LogCategory.SmugMug);
        }

        /// <summary>
        /// Insert custom headers into the outgoing request.
        /// </summary>
        /// <param name="request">
        /// Request to insert customer headers into.
        /// </param>
        private void InsertCustomRequestHeaders(ref Message request)
        {
            Object messagePropertyObject;
            HttpRequestMessageProperty messageProperty;

            if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out messagePropertyObject))
            {
                messageProperty = (HttpRequestMessageProperty)messagePropertyObject;
            }
            else
            {
                messageProperty = new HttpRequestMessageProperty();
            }

            this.InsertUserAgentHeader(messageProperty);
            request.Properties[HttpRequestMessageProperty.Name] = messageProperty;
        }

        /// <summary>
        /// Set the User-Agent to the Obra custom value.
        /// </summary>
        private void InsertUserAgentHeader(
            HttpRequestMessageProperty property)
        {
            property.Headers.Add(
                HttpRequestHeader.UserAgent,
                Obra.Api.Strings.UserAgent);
        }


        /// <summary>
        /// Enables inspection or modification of a message before a request 
        /// message is sent to a service.
        /// </summary>
        /// <param name="request">
        /// The message to be sent to the service.
        /// </param>
        /// <param name="channel">
        /// The WCF client object channel.
        /// </param>
        /// <returns>
        /// The object that is returned as the correlationState argument of the 
        /// System.ServiceModel.Dispatcher.IClientMessageInspector.AfterReceiveReply(System.ServiceModel.Channels.Message@,System.Object)
        /// This is null if no correlation state is used.  The best practice is 
        /// to make this a System.Guid to ensure that no two correlationState objects
        /// are the same.
        /// </returns>
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            this.InsertCustomRequestHeaders(ref request);

            // Bow to SmugMug's view of the world.
            string uriString = request.Headers.To.ToString()
                .Replace("=false", "=0")
                .Replace("=true",  "=1");

            request.Headers.To = new Uri(uriString);

            Log.Debug(
                request.Headers.To.ToString(),
                LogCategory.REST,
                LogCategory.SmugMug);

            return null;
        }

        #endregion
    }
}
